<?php

/**
 * @Author: lujizhang
 * @Date:   2019-10-16 09:26:11
 * @Last Modified by:   lujizhang
 * @Last Modified time: 2019-11-01 18:04:10
 */

namespace app\api\model;
use think\Db;
use app\api\model\Wechat;
use wechat\component\WXBizMsgCrypt;

class WechatMessage extends Wechat {
    
    function __construct(){
        parent::__construct();
    }

    
    /**
     * 获取微信公众号当前自动回复的内容
     * @param  [type] $access_token [description]
     * @return [type]               [description]
     */
    public function getWxAutoResponse($access_token){
        $url=$this->wxApiBase."/get_current_autoreply_info?access_token=".$access_token;
        $para['type']='news';
        $para['offset']=140;
        $para['count']=20;
        $ret=https_request($url,json_encode($para));
        //subLog("wx_response",json_decode($ret),false,true);
        return $ret;
    }

    /**
     * 响应微信请求 根据响应类型输出不同内容
     * @param  [type] $wx_return    [description]
     * @param  [type] $retContent   [description]
     * @param  string $access_token [description]
     * @param  string $type         [description]
     * @param  array  $more         [description]
     * @return [type]               [description]
     */
    public function responseToWeixin($wx_return,$retContent,$access_token="",$type="text",$more=array()){

        $msg=" ";
        subLog($retContent,'responseToWeixin origin','wechat');
        if($retContent!=="") $msg = $this->transmit($wx_return,$retContent,$type,$more);
        subLog($msg,'responseToWeixin crypted','wechat');
        ob_end_clean();
        header("Connection: close");//告诉浏览器，连接关闭了，这样浏览器就不用等待服务器的响应
        header("HTTP/1.1 200 OK"); //可以发送200状态码，以这些请求是成功的，要不然可能浏览器会重试，特别是有代理的情况下
        ob_start();
        echo $msg;
        flush();

        ob_end_flush();
        flush();

        //sleep(1);

        //响应完转入后台执行
        ignore_user_abort(true);
    }

    /**
     * 格式化响应内容
     * @param  [type] $object  [description]
     * @param  [type] $content []
     * @param  string $type    [type=text 文本消息 type=text_img 图文消息]
     * @param  array  $more    [description]
     * @return [type]          [description]
     */
    private function transmit($object, $content, $type = "text",$more=array(),$encrypt = true)
    {
        if (!isset($content) || empty($content)){
            return "";
        }
        switch ($type) {
            case 'image':
                $content="
                <Image>
                    <MediaId><![CDATA[".$content."]]></MediaId>
                </Image>";
                break;
            case 'voice':
                $content="
                <Voice>
                    <MediaId><![CDATA[".$content."]]></MediaId>
                </Voice>";
                break;
            case 'video':
                $content="
                <Video>
                    <MediaId><![CDATA[".$content."]]></MediaId>
                    <Title><![CDATA[".$more['title']."]]></Title>
                    <Description><![CDATA[".$more['description']."]]></Description>
                </Video>";
                break;
            case 'music':
                $content="
                <Music>
                <Title><![CDATA[".$more['title']."]]></Title>
                <Description><![CDATA[".$more['description']."]]></Description>
                <MusicUrl><![CDATA[".$more['music_url']."]]></MusicUrl>
                <HQMusicUrl><![CDATA[".$more['hq_music_url']."]]></HQMusicUrl>
                <ThumbMediaId><![CDATA[".$content."]]></ThumbMediaId>
                </Music>
            ";
                break;
            case 'news':
                $content="
                <ArticleCount>".$more['count']."</ArticleCount>
                <Articles>
                ";
                foreach($more['items'] as $item){
                    $content.="
                        <item>
                        <Title><![CDATA[".$item['title']."]]></Title>
                        <Description><![CDATA[".$item['description']."]]></Description>
                        <PicUrl><![CDATA[".$item['picurl']."]]></PicUrl>
                        <Url><![CDATA[".$item['url']."]]></Url>
                        </item>
                    ";
                }
                $content.="
                </Articles>
            ";

                break;
            case "text":
                $content="
                <Content><![CDATA[".$content."]]></Content>
                ";
                break;
            default:
                $content="
                <Content><![CDATA[".$content."]]></Content>
                ";
                break;
        }

        $xmlTpl = "<xml>
            <ToUserName><![CDATA[%s]]></ToUserName>
            <FromUserName><![CDATA[%s]]></FromUserName>
            <CreateTime>%s</CreateTime>
            <MsgType><![CDATA[%s]]></MsgType>
            %s
        </xml>";

        $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, time(), $type,$content);
        if($encrypt){
            $encryptMsg = '';
            $timeStamp = time();
            $nonce = substr(md5('sanyouwechatmsg'.date("Y-m-d H:i:s")),0,8);
            $token = $this->component_msg_token;
            $encodingAesKey = $this->component_msg_aeskey;
            $appId = $this->component_appid;
            $pc = new WXBizMsgCrypt($token, $encodingAesKey, $appId); 
            $code = $pc->encryptMsg($result, $timeStamp, $nonce, $encryptMsg);
            $result = $encryptMsg;
        }
        return $result;
    }


    public function sendMsgToUser($toUser, $param,$msgType="text")
    {
        
        $requestUrl=$this->wxApiBase."/message/custom/send?access_token=".$this->accessToken;
        $arr = [];
        $arr['touser']=$toUser;
        $arr['msgtype']=$msgType;

        switch ($msgType){
            case "text":
                $arr['text']=array('content'=>urlencode($param['content']));
                break;
            case "image":
                $arr['image']=array("media_id"=>$param['media_id']);
                break;
            case "voice":
                $arr['voice']=array("media_id"=>$param['media_id']);
                break;
            case "video":
                $arr['voice']=array("media_id"=>$param['media_id']
                ,"thumb_media_id"=>$param['thumb_media_id'],"title"=>$param['title']
                ,"description"=>$param['description']);
                break;
            case "news":
                $arr['news']['articles'][]=array("title"=>$param['title']
                ,"url"=>$param['newsUrl'],"picurl"=>$param['picUrl']
                ,"description"=>$param['description']);
                break;
            default:
                break;
        }
        subLog($requestUrl,'send msg url','wechat');
        subLog(urldecode(json_encode($arr)),'send msg data','wechat');
        $data=$this->httpRequest($requestUrl,urldecode(json_encode($arr)));
        return $data;
    }

    /**
     * 获取微信资源ID
     * @param  [type] $mediaName [description]
     * @return [type]            [description]
     */
    public function getWxMaterial($mediaName,$param=[]){
        $access_token = $this->accessToken;
        $url=$this->wxApiBase."/material/batchget_material?type=image&access_token=".$access_token;
        
        $param['type']='image';
        $param['offset']=0;
        $param['count']=20;
        $postdata=json_encode($param);
        $ret=https_request($url,$postdata);
        $arr=json_decode($ret,true);
        foreach($arr['item'] as $item){
            if($item['name']==$mediaName){
                $mediaId=$item['media_id'];
                break;
            }
        }
        return $mediaId;
    }


    public function getDecryptWxMessage(){
        $param = input('param.');
        $postData = \file_get_contents('php://input');
        // subLog($postData,'wx postdata','wechat');
        $appId = $this->component_appid;
        $encodingAesKey = $this->component_msg_aeskey;
        $token = $this->component_msg_token;
        $timeStamp = $param['timestamp'];
        $nonce = $param['nonce'];
        $msg_sign = $param['msg_signature'];
        // $signature = !empty($param['signature'])?$param['signature']:'';
        
        $encryptMsg = $postData;
        // subLog($token,'getDecryptWxMessage token','wechat');
        // subLog($encodingAesKey,'getDecryptWxMessage encodingAesKey','wechat');
        // subLog($appId,'getDecryptWxMessage appId','wechat');
        $pc = new WXBizMsgCrypt($token, $encodingAesKey, $appId);
        $from_xml = $encryptMsg;
        $xml_tree = new \DOMDocument();
        $xml_tree->loadXML($encryptMsg);
        $array_e = $xml_tree->getElementsByTagName('Encrypt');
        $encrypt = $array_e->item(0)->nodeValue;
        
        // 这里必须有ToUserName 字段否则需要改XMLParse文件

        $format = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><Encrypt><![CDATA[%s]]></Encrypt></xml>";
        $from_xml = sprintf($format, $encrypt);
        
        // 第三方收到公众号平台发送的消息
        $msg = '';
        // subLog($msg_sign.';'.$timeStamp.':'.$nonce.':'.$appId,'decrypt param','wechat');
        $errCode = $pc->decryptMsg($msg_sign, $timeStamp, $nonce, $from_xml, $msg);
        

        if ($errCode == 0) {
            // subLog("解密后: " . $msg . "\n","decryptMsg",'wechat');
            return $msg;
        } else {
            subLog($errCode . "\n",'decryptMsgError','wechat');
            return false;
        }
    }

}